import * as vscode from 'vscode';
import { ApiClient } from '../utils/apiClient';

export class FuzzTestService {
    private apiClient: ApiClient;

    constructor(apiClient: ApiClient) {
        this.apiClient = apiClient;
    }

    async generateFuzzTest(
        editor: vscode.TextEditor,
        token: vscode.CancellationToken
    ): Promise<string> {
        const codeContext = this.buildCodeContext(editor);
        
        // 构建Fuzz测试生成的提示词
        const prompt = this.buildFuzzTestPrompt(codeContext);
        
        // 使用LLM生成Fuzz测试
        const systemPrompt = `你是一个专业的C++ Fuzz测试生成专家，专门为OpenHarmony项目生成高质量的Fuzz测试。
请遵循以下规范：
1. 使用libFuzzer框架
2. 生成有效的Fuzz目标函数
3. 包含边界值测试和异常输入测试
4. 遵循OpenHarmony的编码规范
5. 包含详细的测试注释和说明`;

        return await this.apiClient.generateWithLLM(prompt, systemPrompt);
    }

    private buildCodeContext(editor: vscode.TextEditor): any {
        const document = editor.document;
        const position = editor.selection.active;
        
        return {
            filePath: document.fileName,
            code: document.getText(),
            cursorLine: position.line,
            cursorColumn: position.character,
            language: this.detectLanguage(document.fileName),
            projectRoot: this.getProjectRoot(document.uri)
        };
    }

    private buildFuzzTestPrompt(codeContext: any): string {
        const { code, filePath } = codeContext;
        
        // 提取函数和类信息
        const functions = this.extractFunctions(code);
        const classes = this.extractClasses(code);
        
        let prompt = `请为以下C++代码生成完整的Fuzz测试：\n\n`;
        prompt += `文件路径: ${filePath}\n\n`;
        prompt += `代码内容:\n\`\`\`cpp\n${code}\n\`\`\`\n\n`;
        
        if (functions.length > 0) {
            prompt += `需要Fuzz测试的函数:\n`;
            functions.forEach(func => {
                prompt += `- ${func.name}: ${func.signature}\n`;
            });
            prompt += `\n`;
        }
        
        if (classes.length > 0) {
            prompt += `需要Fuzz测试的类:\n`;
            classes.forEach(cls => {
                prompt += `- ${cls.name}: ${cls.description}\n`;
            });
            prompt += `\n`;
        }
        
        prompt += `请生成包含以下内容的Fuzz测试文件：
1. 必要的头文件包含（包括libFuzzer相关头文件）
2. Fuzz目标函数的定义
3. 每个函数的Fuzz测试用例
4. 边界值和异常输入的测试
5. 内存泄漏和缓冲区溢出的检测
6. 详细的测试注释和说明

请确保Fuzz测试代码可以直接编译和运行，并且能够发现潜在的安全漏洞和bug。`;

        return prompt;
    }

    private extractFunctions(code: string): Array<{name: string, signature: string}> {
        const functions: Array<{name: string, signature: string}> = [];
        
        // 匹配函数定义
        const functionRegex = /(\w+(?:\s+\w+)*)\s+(\w+)\s*\([^)]*\)\s*(?:const\s*)?\s*{/g;
        let match;
        
        while ((match = functionRegex.exec(code)) !== null) {
            const returnType = match[1].trim();
            const functionName = match[2].trim();
            const signature = `${returnType} ${functionName}(...)`;
            
            functions.push({
                name: functionName,
                signature: signature
            });
        }
        
        return functions;
    }

    private extractClasses(code: string): Array<{name: string, description: string}> {
        const classes: Array<{name: string, description: string}> = [];
        
        // 匹配类定义
        const classRegex = /class\s+(\w+)(?:\s*:\s*[^{]+)?\s*{/g;
        let match;
        
        while ((match = classRegex.exec(code)) !== null) {
            const className = match[1];
            classes.push({
                name: className,
                description: `类 ${className}`
            });
        }
        
        return classes;
    }

    private detectLanguage(fileName: string): string {
        if (fileName.endsWith('.c')) return 'c';
        if (fileName.endsWith('.cpp') || fileName.endsWith('.cc') || fileName.endsWith('.cxx')) return 'cpp';
        if (fileName.endsWith('.h')) return 'cpp';
        return 'cpp';
    }

    private getProjectRoot(uri: vscode.Uri): string {
        const workspaceFolder = vscode.workspace.getWorkspaceFolder(uri);
        return workspaceFolder ? workspaceFolder.uri.fsPath : '';
    }
}
